/**
 * @Author yang
 * @Description json 化时间格式自定义
 * @Date 2021/2/26
 * @Time 9:20
 **/
package elastic

import (
	"errors"
	"regexp"
	"strings"
	"time"
)

const (
	DateTime = "2006-01-02 15:04:05"
	Date     = "2006-01-02"
	Date1    = "2006/01/02"
	Time     = "15:04:05"

	ZhDate        = "2006年01月02日"
	ZhDateTime    = "2006年01月02日 15:04:05"
	ZhAllDateTime = "2006年01月02日 15时04分05秒"
	ZhTime        = "15时04分05秒"
)

type FormateType string

// define costome time format by delare a new type, then add a  dalare case
type MTime mTime

func Formate(formateType interface{}) string {
	fomart := time.RFC3339Nano
	switch formateType.(type) {
	case MTime:
		fomart = ZhAllDateTime
	}
	return fomart
}

// =====================实现部分=======================

type mTime time.Time

func NewMTime(timePoint time.Time) MTime {
	mTime := mTime(timePoint)
	return MTime(mTime)
}

// MarshalJSON implements the json.Marshaler interface.
// The time is a quoted string in RFC 3339 format, with sub-second precision added if present.
func (t MTime) MarshalJSON() ([]byte, error) {
	if y := time.Time(t).Year(); y < 0 || y >= 10000 {
		// RFC 3339 is clear that years are 4 digits exactly.
		// See golang.org/issue/4556#c15 for more discussion.
		return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
	}

	b := make([]byte, 0, len(Formate(t))+2)
	b = append(b, '"')
	b = time.Time(t).AppendFormat(b, Formate(t))
	b = append(b, '"')
	return b, nil
}

// UnmarshalJSON implements the json.Unmarshaler interface.
// The time is expected to be a quoted string in RFC 3339 format.
func (t *MTime) UnmarshalJSON(data []byte) error {
	// Ignore null, like in the main JSON package.
	if string(data) == "null" {
		return nil
	}
	// Fractional seconds are handled implicitly by Parse.
	var err error
	formate := autoRecognizeFomate(string(data))
	//fmt.Println("===unmarshal formate==> ", formate)

	timePoint, err := time.Parse(formate, string(data))
	*t = NewMTime(timePoint)
	return err
}

var timeReplaceEles = []string{"2006", "01", "02", "15", "04", "05"}

func autoRecognizeFomate(timeStr string) (res string) {
	compileStr, _ := regexp.Compile("[\\d]+")
	submatch := compileStr.FindAllStringSubmatch(timeStr, -1)
	replaceCount := 0
	switch len(submatch) {
	case 6:
		res = compileStr.ReplaceAllStringFunc(timeStr, func(timeStr string) (res string) {
			res = timeReplaceEles[replaceCount]
			replaceCount += 1
			//fmt.Println("=====> ", timeStr, replaceCount)
			return
		})
	case 5:
		fallthrough
	case 4:
		res = compileStr.ReplaceAllStringFunc(timeStr, func(timeStr string) (res string) {
			// 未带年份
			if replaceCount == 0 && len(timeStr) < 4 {
				replaceCount += 1
			}
			res = timeReplaceEles[replaceCount]
			replaceCount += 1
			//fmt.Println("=====> ", timeStr, replaceCount)
			return
		})
	case 3:
		res = compileStr.ReplaceAllStringFunc(timeStr, func(timeStr string) (res string) {
			// 未带年份
			if replaceCount == 0 && len(timeStr) < 4 {
				replaceCount += 3
			}
			res = timeReplaceEles[replaceCount]
			replaceCount += 1
			//fmt.Println("=====> ", timeStr, replaceCount)
			return
		})

	case 2:
		res = compileStr.ReplaceAllStringFunc(timeStr, func(timeStr string) (res string) {
			// 未带年份
			if replaceCount == 0 &&
				(strings.Contains(timeStr, ":") ||
					strings.Contains(timeStr, "时") ||
					strings.Contains(timeStr, "分")) {
				replaceCount += 3
			} else if replaceCount == 0 && len(timeStr) < 4 {
				replaceCount += 1
			}
			res = timeReplaceEles[replaceCount]
			replaceCount += 1
			//fmt.Println("=====> ", timeStr, replaceCount)
			return
		})

	}
	res = strings.TrimSpace(res)
	return
}
